<?php
/**
 * 
 * Fdatabase.php
 * @author Igor Di Paolo <igor.di.paolo@gmail.com>
 * @package Foundation
 */
/**
 * Fdatabase
 * @author Igor Di Paolo <igor.di.paolo@gmail.com>
 * @package Foundation
 *
 */
abstract class Fdatabase extends Object{
	/**
	 * Mysqli
	 * @var mysqli $mysqli
	 */
	private static $mysqli = null;
	/** 
	 * Nome tabella
	 * @var string
	 */
	protected $table;
	/**
	 * Nome della classe entity da restituire
	 * @var string
	 */
	protected $entity;
	/**
	 * Array contenente le chiavi 
	 * @var array
	 */
	protected $key;
	/**
	 * Risultato di una query precedente
	 * @var mixed $result
	 */
	private $result;
	/**
	 * affectedRows
	 * @var number $affectedRows
	 */
	protected $affectedRows = 0;
	/**
	 * Costruttore
	 * @param string $entity
	 * @param string $table
	 * @param array $key
	 */
	public function __construct($entity,$table,$key) {
		$this->entity = $entity;
		$this->table = $table;
		$this->key = $key;
		
		if(!self::$mysqli) {
			self::_connect();
		}
	}
	/**
	 * Connessione al Database
	 * @throws ExceptionDB
	 */
	public static function _connect() {
		//Gia' connesso
		if(self::$mysqli){
			return;
		}
		
		self::$mysqli = new mysqli(DB_URL,DB_USER,DB_PASS,DB_NAME);
		if($error = self::$mysqli->connect_errno) {
			throw new ExceptionDB('Errore di connessione al db',$error);
		}
		
		$log = new ULogDB();
		$log->log('Connected to Database !');
		
	}
	/**
	 * search
	 * Cerca nella tabella, usando i parametri forniti dall'utente
	 * @param mixed $cols
	 * @param array $where
	 * @param array $order
	 * @param array $limit
	 */
	public function search($cols = null,$where = null,$order = null,$limit = null){
		
		/**
		 * Costruzione della query
		 */
		
		$query = 'SELECT ' ;
		
		if(!is_null($cols) && is_array($cols)) {
			$query .= implode($cols,',').' ';
		} else {
			$query .= '* ';
		}
		
		$query .= ' FROM '.$this->table.' ';
		
		/**
		 * Clausola Where
		 */
		
		if(!is_null($where)) {
			
			$query .= 'WHERE ';
		
			if(is_array($where)){
				
				$i = 0;
				
				foreach($where as $key=>$value){
					if($i == 0){
						$i++;
						$query .= '`'.$key.'`=\''.$this->safeString($value).'\' ' ;
					} else {
						$query .= 'AND `'.$key.'`=\''.$this->safeString($value).'\' ';
					}
				}
			}
		}
		
		/**
		 * Clausola ORDER BY
		 */ 
		
		if(is_array($order)) {
			
			$query .= 'ORDER BY ';
			$i = 0;
			
			foreach($order as $key => $order){
				if($i == 0){
					$i++;
					$query .= $key.' '.$order;
				}else {
					$query .= ','.$key.' '.$order;
				}
			}
		}
		
		/**
		 * Clausola LIMIT
		 */
		//TODO: limit
		
		if($limit != null && is_array($limit)){
			$query .= 'LIMIT '.$limit[0].','.$limit[1];
		}
		
		$query .= ';';
		
		/**
		 * Eseguo la query
		 */
		
		$this->_query($query);
		
			
	}
	/**
	 * store
	 * Salva un oggetto nella corrispondente tabella
	 * @param EEntity $object
	 */
	public function store(EEntity $object) {
		
		$query = 'INSERT INTO '.$this->table.' ';
		$fields = '(';
		$values = '(';
		$object = $object->toArray();
		foreach($object as $key=>$value) {
			if($value == null){
				continue;
			}
			$fields .= '`'.$key.'`,';
			if ($this->safeString($value) != NULL) {
				$values .= '\''.$this->safeString($value).'\',';
			}
			else {
				$values .= 'NULL,';
			}
		}
		
		
		$fields = rtrim($fields,',');
		$values = rtrim($values,',');

		$fields .= ')';
		$values .= ')';
		
		$query .= $fields.' VALUES '.$values.' ;';
		
		$this->_query($query);
		
	}
	/**
	 * update
	 * @param EEntity $object
	 */
	public function update(EEntity $object){
		
		$query = 'UPDATE '.$this->table.' SET ';
		
		$object = $object->toArray();
		foreach($object as $key=>$value) {
			if ($this->safeString($value) != NULL) {
				$query .= '`'.$key.'`=\''.$this->safeString($value).'\',';
			}
			else {
				$query .= '`'.$key.'`=NULL,';
			}
		}
		
		$query = rtrim($query,',');
		$query .= ' WHERE ';
		
		$i = 0;
		
		if(is_array($this->key)){
			
			foreach($this->key as $key){
				if($i == 0){
					$query .= '`'.$key.'`=\''.$this->safeString($object[$key]).'\'' ;
					$i++;
				} else {
					$query .= ' AND `'.$key.'`=\''.$this->safeString($object[$key]).'\'';
				}
			}
		} else {
			$query .= '`'.$this->key.'`=\''.$this->safeString($object[$this->key]).'\'' ;
		}
			
		$query .= ';';
		
		$this->_query($query);
		
	}
	/**
	 * load
	 * @param array $params
	 * @throws ExceptionDB
	 */
	public function load($params = null) {
		if(is_array($params)) {
			return $this->search('*',$params);
		} else {
			throw new ExceptionDB('Parametri non corretti', 12);
		}
	}
	/**
	 * _query
	 * @param string $query
	 * @throws ExceptionDB
	 */
	final protected function _query($query) {
		
		$debug = new ULogDB();
		$debug->log($query);
		
		$this->result = self::$mysqli->query($query);
		$this->affectedRows = self::$mysqli->affected_rows;
		
		if(self::$mysqli->errno){
			throw new ExceptionDB('Mysql Error', self::$mysqli->errno);
		}
	}
	/**
	 * query
	 * @param string $query
	 * @throws ExceptionDB
	 */
	public static function query($query) {
		$debug = new ULogDB();
		$debug->log($query);
		
		if(self::$mysqli == null){
			self::_connect();
		}
		
		$result = self::$mysqli->query($query);
		
		if(self::$mysqli->errno){
			throw new ExceptionDB('Mysql Error', self::$mysqli->errno);
		}
		
		return $result;
		
	}
	/**
	 * multi_query
	 * @param string $query
	 * @throws ExceptionDB
	 */
	public static function multi_query($query){
		$debug = new ULogDB();
		$debug->log($query);
		
		if(self::$mysqli == null){
			self::_connect();
		}
		
		$result = self::$mysqli->multi_query($query);
		
		if(self::$mysqli->errno){
			throw new ExceptionDB('Mysql Error', self::$mysqli->errno);
		}
		
		return $result;
	}
	/**
	 * delete
	 * @param string $where
	 */
	public function delete($where){
		$query .= 'DELETE FROM '.$this->table.' WHERE ';
		
		if(is_array($where)){
				
				$i = 0;
				
				foreach($where as $key=>$value){
					if($i == 0){
						$i++;
						$query .= '`'.$key.'`=\''.$this->safeString($value).'\'' ;
					} else {
						if ($this->safeString($value) != NULL) {
							$query .= ' AND `'.$key.'`=\''.$this->safeString($value).'\'';
						}
						else {
							$query .= ' AND `'.$key.'`=NULL';
						}
					}
				}
			}
			
			$query .= ' ;';
			$this->_query($query);

	}
	
	/**
	 * deleteObj
	 * @param EEntity $object
	 */
	public function deleteObj(EEntity $object){
		$query = 'DELETE FROM '.$this->table.' ';
		
		$object = $object->toArray();
		
		$query .= ' WHERE ';
		
		$i = 0;
		
		if(is_array($this->key)){
				
			foreach($this->key as $key){
				if($i == 0){
					$query .= '`'.$key.'`=\''.$this->safeString($object[$key]).'\'' ;
					$i++;
				} else {
					$query .= ' AND `'.$key.'`=\''.$this->safeString($object[$key]).'\'';
				}
			}
		} else {
			$query .= '`'.$this->key.'`=\''.$this->safeString($object[$this->key]).'\'' ;
		}
		
		$query .= ';';
		
		$this->_query($query);
	}
	
	/**
	 *
	 * getEntities
	 * @return array $result
	 */
	public function getEntities() {
		if(!$this->result) {
			return false;
		}
		
		$res = array();
		
		while($temp = $this->result->fetch_object($this->entity)){
			$res[] = $temp;
		}
		
		$this->result = null;
		
		return $res;
		
	}
	/**
	 * getArray
	 * Restituisce la query per array
	 * @return $array
	 */
	public function getArray() {
		if(!$this->result){
			return false;
		}
		
		$array = array();
		
		while($temp = $this->result->fetch_array(MYSQLI_ASSOC)) {
			$array[] = $temp;
		}
		
		return $array;
	}
	
	/**
	 * getAffectedRows
	 * Restituisce le righe che la query precedente ha interessato
	 */
	public function getAffectedRows() {
		return $this->affectedRows;
	}
	/**
	 * _disconnect
	 */
	public static function _disconnect() {
		
		self::$mysqli->close();
		self::$mysqli = null;
		
		$debug = new ULogDB();
		$debug->log('*** Disconnected from db ***');
		
	}
	/**
	 * safeString
	 * 
	 * safeString usa la funzione mysql_real_escape_string per evitare
	 * mysql injection
	 * 
	 * @param string $string
	 * @return string
	 */
	protected function safeString($string){
		return self::$mysqli->real_escape_string($string);
	}
	
}